#include<iostream>
#include<cstring>
#include<string>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>

void usage(std::string proc)
{
    std::cout << proc << "  server_port" << std::endl;
}

void ServerIo(int sock)
{
    char buff[1024] = {0};
    for(; ;)
    {
        //read
        memset(buff,0,sizeof buff);
        int s = read(sock,buff,sizeof(buff) - 1); //读
        buff[s] = 0;
        //回显信息
        std::cout << "client ## " << buff << std::endl;
        
        //server send to client
        std::string message = ">>>server<<< # ";
        message += buff;
        write(sock,message.c_str(),message.size());
    }
}

int main(int argc , char* argv[])
{
    if(argc != 2)
    {
        usage(argv[0]);
        return 1;
    }

    //1. create
    int listen_sock = socket(AF_INET,SOCK_STREAM,0);
    if(listen_sock < 0)
    {
        std::cerr << " socket error" << errno << std::endl;
        return 2;
    }

    //2.bind
    struct sockaddr_in local;
    memset(&local,0,sizeof local);
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[1]));
    local.sin_addr.s_addr = INADDR_ANY;
    //信号忽略
    signal(SIGCHLD,SIG_IGN);

    if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local)) < 0)
    {
        std::cerr << " bind error" << errno << std::endl;
        return 3;
    }

    //3. listen 
    if(listen(listen_sock,5) < 0)
    {
        std::cerr << " listen error" << errno << std::endl;
        return 4;
    }

    //4. accept / 提供服务
    while(true)
    {
        struct sockaddr_in peer;
        memset(&peer,0,sizeof peer);
        socklen_t len = sizeof(peer);
        //accept
        int new_sock = accept(listen_sock,(struct sockaddr*)&peer,&len);
        if(new_sock < 0) 
        {
            std::cout << "new_sock < 0" << std::endl;
            continue;
        }
        std::cout << "get a new connect" << std::endl;
        int pid = fork();
        if(pid == 0)
        {
            //child 提供服务
            ServerIo(new_sock);
        }
        else if(pid < 0)
        {
            std::cerr << "fork error" << errno << std::endl;
        } 
        else
        {
            //father do none
        }

    }

    return 0;
}